package com.dk.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.dk.data.Result;
import com.dk.data.ResultEnum;
import com.dk.pojo.user.SmsSend;
import com.dk.pojo.user.TbUser;
import com.dk.service.user.UserService;
import com.dk.util.ShiroUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import java.util.Date;

@Controller
@RequestMapping("user")
public class UserController {

    private final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Reference
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;


    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @RequestMapping("isLogin")
    @ResponseBody
    public Result isLogin() {
        Subject subject = SecurityUtils.getSubject();
        TbUser user = (TbUser) subject.getPrincipal();
        try {
            return Result.response(ResultEnum.OK).setData(user);
        } catch (Exception e) {
            logger.error("获取登录数据错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    @RequestMapping("register")
    @ResponseBody
    public Result register(String username,String password,String isPassword,String phone,String code) {
        try {
            if (username == null || username.equals("")
                    || password == null || password.equals("")
                    || isPassword == null || isPassword.equals("")
                    || phone == null || phone.equals("")
                    ||code == null || code.equals("")) {
                return Result.response(ResultEnum.FAIL).setData("账号或密码或手机号或验证码为空");
            }
            HashOperations hashOperations = redisTemplate.opsForHash();
            String user_register = (String) hashOperations.get("user_register", phone);
            System.out.println(user_register);
            if (!code.equals(user_register)) {
                return Result.response(ResultEnum.FAIL).setData("验证码错误");
            }
            TbUser user = userService.getUserByUsername(username);
            if (user != null) {
                return Result.response(ResultEnum.FAIL).setData("用户已经存在");

            }
            String salt = ShiroUtils.generateSalt(6);
            String md5 = ShiroUtils.encryptPassword("MD5", password, salt, 3);
            TbUser tbUser = new TbUser();
            tbUser.setUsername(username);
            tbUser.setPassword(md5);
            tbUser.setPhone(phone);
            tbUser.setStatus("y");
            tbUser.setSalt(salt);
            tbUser.setCreated(new Date());
            tbUser.setUpdated(new Date());
            int i = userService.insertUser(tbUser);
            return Result.response(ResultEnum.OK).setData("注册成功");
        } catch (Exception e) {
            logger.error("用户注册错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    @RequestMapping("login")
    public String login(String username, String password, Model model) {
        try {
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            subject.login(token);
        } catch (UnknownAccountException unknownAccountException) {
            model.addAttribute("massage","用户名错误");
            return "login";
        } catch (IncorrectCredentialsException incorrectCredentialsException) {
            model.addAttribute("massage","密码错误");
            return "login";
        }
        return "redirect:/index";
    }

    @RequestMapping("sendSms")
    @ResponseBody
    public Result sendSms(String phone) {
        try {
            String code = RandomStringUtils.randomNumeric(4);
            SmsSend smsSend = new SmsSend(phone,code);
            rocketMQTemplate.convertAndSend("dongdongshop-Sms",smsSend);
            return Result.response(ResultEnum.OK);
        } catch (Exception e) {
            logger.error("发送短信错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    @RequestMapping("sendSmsApi")
    @ResponseBody
    public Result sendSmsApi(String phone) {
        try {

            String code = RandomStringUtils.randomNumeric(4);
            HashOperations hashOperations = redisTemplate.opsForHash();
            hashOperations.put("user_register",phone,code);
            String accessKeyId = "LTAI4Fz7e5aqwbXHSqS7grS8";
            String accessSecret = "qsIhqBLuWDiSiOpcEb8vU6l3Bc7i8z";
            java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
            df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
            java.util.Map<String, String> paras = new java.util.HashMap<String, String>();
            // 1. 系统参数
            paras.put("SignatureMethod", "HMAC-SHA1");
            paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
            paras.put("AccessKeyId", accessKeyId);
            paras.put("SignatureVersion", "1.0");
            paras.put("Timestamp", df.format(new java.util.Date()));
            paras.put("Format", "XML");
            // 2. 业务API参数
            paras.put("Action", "SendSms");
            paras.put("Version", "2017-05-25");
            paras.put("RegionId", "cn-qingdao");
            paras.put("PhoneNumbers", phone);
            paras.put("SignName", "DYN商城");
            paras.put("TemplateParam", "{\"code\":"+code+"}");
            paras.put("TemplateCode", "SMS_194061587");
            paras.put("OutId", "123");
            // 3. 去除签名关键字Key
            if (paras.containsKey("Signature"))
                paras.remove("Signature");
            // 4. 参数KEY排序
            java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
            sortParas.putAll(paras);
            // 5. 构造待签名的字符串
            java.util.Iterator<String> it = sortParas.keySet().iterator();
            StringBuilder sortQueryStringTmp = new StringBuilder();
            while (it.hasNext()) {
                String key = it.next();
                sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
            }
            String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
            StringBuilder stringToSign = new StringBuilder();
            stringToSign.append("GET").append("&");
            stringToSign.append(specialUrlEncode("/")).append("&");
            stringToSign.append(specialUrlEncode(sortedQueryString));
            String sign = sign(accessSecret + "&", stringToSign.toString());
            // 6. 签名最后也要做特殊URL编码
            String signature = specialUrlEncode(sign);
            System.out.println("signature"+signature);

            // 最终打印出合法GET请求的URL
            String url = "http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp;
            return Result.response(ResultEnum.OK).setData(url);
        } catch (Exception e) {
            logger.error("发送短信错误",e);
            return Result.response(ResultEnum.FAIL);
        }
    }

    public static String specialUrlEncode(String value) throws Exception {
        return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    public static String sign(String accessSecret, String stringToSign) throws Exception {
        javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }
}
